package parser;

/*
 * Parser for delete
 * Takes in command from GUI.Main, and call appropriate method in delete
 * 
 */

import java.util.PriorityQueue;
import java.util.Stack;

import logger.Logger;
import logic.Delete;
import logic.Display;
import memory.Memory;

public class ParserDelete extends ParserMain {

	
	private static final String ERROR_ONE_OR_MORE_INDEX_ARE_INVALID = "Error: one or more index are invalid.";
	private static final String INVALID_DELETE_COMMAND = "You may only delete after a search or delete directly by delete <taskName>.";
	private static final String NO_TASK_DELETED = "No task deleted";
	
	private static final String SPACE = " ";
	
	private static final int DELETE_FROM_DETAILED = 54;
	private static final int DELETE_DIRECTLY = 53;
	private static final int DELETE_AFTER_SEARCH = 52;
	
	private static final int INVALID = -1;

	//@author A0085082E
	/*
	 * Run delete as called by GUI.Main
	 */
	public static void run(String command, Memory memory){
		initVar();
		setCommand(command);
		delete(memory);
	}

	//@author A0085082E
	/*
	 * initialise variables
	 */
	private static void initVar(){
		setType(INVALID);
		setTaskName(null);
	}

	//@author A0085082E
	/*
	 * Takes in command and memory
	 * Set command type and call method corresponding to the command.
	 * 
	 */
	private static void delete(Memory memory){
		setDeleteType();
		runCodeIfCommandIsValid(memory);
	}

	//@author A0085082E
	/*
	 * Check if command is valid
	 * If command is invalid, generate error message.
	 * If command is valid, run delete
	 */
	private static void runCodeIfCommandIsValid(Memory memory) {
		switch (type) {
		case DELETE_AFTER_SEARCH:
			deleteAfterSearch(memory);

			break;

		case DELETE_DIRECTLY:
			deleteDirectly(memory);
			break;

		case DELETE_FROM_DETAILED:
			deleteFromDetailed(memory);
			break;

		default:
			System.out.println(INVALID_DELETE_COMMAND);
			Logger.add(LOGGER_ERROR + INVALID_DELETE_COMMAND);

		}
	}

	//@author A0085082E
	/*
	 * set delete type
	 */
	private static void setDeleteType() {
		if(command.length() == 0){
			setType(DELETE_FROM_DETAILED);
		}else if(isDeleteAfterSearch(command)){
			setType(DELETE_AFTER_SEARCH);
		}else{
			setType(DELETE_DIRECTLY);
		}
	}

	//@author A0085082E
	/*
	 * checks if user is in detailed view. If so, call deleteDetailed
	 */
	private static void deleteFromDetailed(Memory memory){
		if (Display.detailedView != null){
			Delete.deleteDetailed(memory);
		}
	}

	//@author A0085082E
	/*
	 * Takes in index of items to be deleted 
	 * Puts index into a priority queue, then reverse it.
	 * if list is empty, return an error because index are invalid (e.g. out of bound)
	 * if list is not empty, calls deleteAfterSearch
	 */
	private static void deleteAfterSearch(Memory memory) {
		PriorityQueue<Integer> ascendingQueue = deleteIndex();
		Stack<Integer> descendingList = reverseQueue(ascendingQueue);
		if(descendingList.isEmpty()){
			System.out.println(ERROR_ONE_OR_MORE_INDEX_ARE_INVALID);
			Logger.add(LOGGER_ERROR + ERROR_ONE_OR_MORE_INDEX_ARE_INVALID);
		}else{
			Delete.deleteAfterSearch(descendingList, memory);
		}
	}

	//@author A0085082E
	/*
	 * Delete directly delete items with the exact taskname.
	 * User input is set as taskName.
	 * If taskName is not empty, deleteDirectly is called
	 * Otherwise error message is generated
	 */
	private static void deleteDirectly(Memory memory) {
		setTaskName(command);
		if(taskName != null){
			Delete.deleteDirectly(taskName, memory);
		}else{
			System.out.println(NO_TASK_DELETED);
			Logger.add(LOGGER_ERROR + NO_TASK_DELETED);
		}
	}

	//@author A0096677H
	/*
	 * Reverse the index stored in the priority queue by storing into a stack
	 */
	private static Stack<Integer> reverseQueue(PriorityQueue<Integer> ascendingQueue) {
		Stack<Integer> newList = new Stack<Integer>();
		while (!ascendingQueue.isEmpty()){
			newList.push(ascendingQueue.poll());
		}
		return newList;
	}

	//@author A0085082E
	/*
	 * Check if command is deleteaftersearch
	 * Returns true the string contains number only
	 */
	private static boolean isDeleteAfterSearch(String command){
		String[] details = command.split(SPACE);
		for(int i = 0; i < details.length; i++){
			if(!isNumeric(details[i])){
				return false;
			}
		}
		return true;
	}

	//@author A0085082E
	/*
	 * remove duplicate and out of bound index from the priority queue
	 */
	private static PriorityQueue<Integer> deleteIndex(){

		String[] rawIndex = command.split(SPACE);

		PriorityQueue<Integer> queue  = removeDuplicateAndOutOfBound(rawIndex);
		return queue;
	}

}
